package com.yzy.fly.config;

import com.yzy.fly.FlySpringMap;
import com.yzy.fly.util.FieldUtil;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.method.ControllerAdviceBean;
import org.springframework.web.method.annotation.ExceptionHandlerMethodResolver;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.HandlerMethodArgumentResolverComposite;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite;
import org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class FlyExceptionHandlerExceptionResolver extends ExceptionHandlerExceptionResolver {

    @Override
    public void afterPropertiesSet() {
        // Do this first, it may add ResponseBodyAdvice beans
        super.afterPropertiesSet();
//        if (this.argumentResolvers == null) {
//            List<HandlerMethodArgumentResolver> resolvers = getDefaultArgumentResolvers();
//            this.argumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);
//        }
//        if (this.returnValueHandlers == null) {
//            List<HandlerMethodReturnValueHandler> handlers = getDefaultReturnValueHandlers();
//            this.returnValueHandlers = new HandlerMethodReturnValueHandlerComposite().addHandlers(handlers);
//        }

        Field field_exceptionHandlerAdviceCache = FieldUtil.getField(ExceptionHandlerExceptionResolver.class, "exceptionHandlerAdviceCache", false);
        Field field_responseBodyAdvice = FieldUtil.getField(ExceptionHandlerExceptionResolver.class, "responseBodyAdvice", false);

        Map<ControllerAdviceBean, ExceptionHandlerMethodResolver> exceptionHandlerAdviceCache = FieldUtil.getFieldValue(field_exceptionHandlerAdviceCache, this);
        List<Object> responseBodyAdvice = FieldUtil.getFieldValue(field_responseBodyAdvice, this);


        int beanSize = exceptionHandlerAdviceCache.size();
        int handlerSize = 0;
        int adviceSize = responseBodyAdvice.size();
//        if (handlerSize == 0 && adviceSize == 0) {
//            logger.debug("ControllerAdvice beans: none");
//        }
//        else {
//            logger.debug("ControllerAdvice beans: " +
//                    handlerSize + " @ExceptionHandler, " + adviceSize + " ResponseBodyAdvice");
//        }
        Field field_mappedMethods = FieldUtil.getField(ExceptionHandlerMethodResolver.class, "mappedMethods", false);

        for (ControllerAdviceBean controllerAdviceBean : exceptionHandlerAdviceCache.keySet()) {
            ExceptionHandlerMethodResolver exceptionHandlerMethodResolver = exceptionHandlerAdviceCache.get(controllerAdviceBean);
            Map<Class<? extends Throwable>, Method> mappedMethods = FieldUtil.getFieldValue(field_mappedMethods, exceptionHandlerMethodResolver);
            handlerSize += mappedMethods.size();
        }

        FlySpringMap.getInstance().add("ExceptionHandlerExceptionResolver.Count.ControllerAdviceBean", beanSize);
        FlySpringMap.getInstance().add("ExceptionHandlerExceptionResolver.Count.@ExceptionHandler", handlerSize);
        FlySpringMap.getInstance().add("ExceptionHandlerExceptionResolver.Count.ResponseBodyAdvice", adviceSize);

    }

}
